package com.xbongbong.saas.help;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.constant.TimeConstant;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.PaasStageEntity;
import com.xbongbong.paas.domain.entity.StageProcessEntity;
import com.xbongbong.paas.domain.entity.StageWorkflowEntity;
import com.xbongbong.paas.domain.entity.ext.OptionalRangeEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.EnableEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.StageSettingEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.sys.help.PackageHelp;
import com.xbongbong.paas.help.ProFormHelp;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.model.StageProcessModel;
import com.xbongbong.paas.model.StageWorkflowModel;
import com.xbongbong.paas.pojo.StageConditionPojo;
import com.xbongbong.paas.pojo.StageListPojo;
import com.xbongbong.paas.pojo.StageSavePojo;
import com.xbongbong.paas.pojo.StageWorkListPojo;
import com.xbongbong.paas.pojo.StageWorkPojo;
import com.xbongbong.paas.pojo.dto.FormDataListDTO;
import com.xbongbong.paas.redis.PaasRedisHelper;
import com.xbongbong.paas.redis.RedisTimeConstant;
import com.xbongbong.paas.service.stage.StageHandle;
import com.xbongbong.paas.service.stage.StageHandleFactory;
import com.xbongbong.paas.service.stage.StageLogHandle;
import com.xbongbong.paas.service.stage.StageLogHandleFactory;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.pro.enums.PackageTypeEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.CustomerStageErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.OutLinkErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.StageWorkEntity;
import com.xbongbong.saas.enums.CompanyConfigEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.model.StageWorkModel;
import com.xbongbong.sys.domain.entity.CompanyConfigEntity;
import com.xbongbong.sys.model.CompanyConfigModel;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 阶段推进器-帮助类
 * @author 李少杰
 * @version v1.0.0
 * @date 2021/11/23 15:09
 */
@Service("stageHelp")
public class StageHelp {

    private static final Logger LOG = LoggerFactory.getLogger(StageHelp.class);

    @Resource
    private StageLogHandleFactory stageLogHandleFactory;
    @Resource
    private StageHandleFactory stageHandleFactory;
    @Resource
    private StageWorkModel stageWorkModel;
    @Resource
    private StageProcessModel stageProcessModel;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private PackageHelp packageHelp;
    @Resource
    private StageWorkflowModel stageWorkflowModel;
    @Resource
    private CompanyConfigModel companyConfigModel;
    @Resource
    private ProFormHelp proFormHelp;
    @Resource
    private PaasRedisHelper paasRedisHelper;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;

    /**
     * 根据阶段流程id查找阶段记录数
     */
    public Integer getStageLogCount(String corpid, Integer saasMark, Integer businessType, Long formId, Long stageProcessId) {
        if (Objects.isNull(corpid) || Objects.isNull(saasMark) || Objects.isNull(businessType) || Objects.isNull(formId) || Objects.isNull(stageProcessId)) {
            return null;
        }
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        params.put(StringConstant.CORPID, corpid);
        params.put(StringConstant.FORM_ID, formId);
        params.put(ParameterConstant.STAGE_PROCESS_ID, stageProcessId);
        params.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());

        StageLogHandle stageLogHandle = stageLogHandleFactory.getStageLogHandle(saasMark, businessType);
        return stageLogHandle.getEntitysCount(params);
    }

    /**
     * 获取当前流程版本的所有阶段
     * @param corpid
     * @param saasMark
     * @param businessType
     * @param formId
     * @param stageProcessId
     * @return
     */
    public List<PaasStageEntity> getStageEntitys(String corpid, Integer saasMark, Integer businessType, Long formId, Long stageProcessId) {
        if (Objects.isNull(corpid) || Objects.isNull(saasMark) || Objects.isNull(formId) || Objects.isNull(stageProcessId)) {
            return new ArrayList<>();
        }
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        params.put(StringConstant.CORPID, corpid);
        params.put(StringConstant.FORM_ID, formId);
        params.put(ParameterConstant.STAGE_PROCESS_ID, stageProcessId);
        params.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        params.put(ParameterConstant.ORDER_BY_STR, " sort " + SortOrder.DESC);

        StageHandle stageHandle = stageHandleFactory.getStageHandle(saasMark, businessType);
        return stageHandle.findEntitys(params);
    }

    /**
     * 根据codeList查找阶段
     * @param corpid
     * @param saasMark
     * @param businessType
     * @param formId
     * @param codeIn
     * @return
     */
    public List<PaasStageEntity> getStageEntitysByCodes(String corpid, Integer saasMark, Integer businessType, Long formId, List<Object> codeIn) {
        if (Objects.isNull(corpid) || Objects.isNull(saasMark) || Objects.isNull(formId) || CollectionsUtil.isEmpty(codeIn)) {
            return new ArrayList<>();
        }
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        params.put(StringConstant.CORPID, corpid);
        params.put(StringConstant.FORM_ID, formId);
        params.put("codeIn", codeIn);
        params.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        StageHandle stageHandle = stageHandleFactory.getStageHandle(saasMark, businessType);
        return stageHandle.findEntitys(params);
    }

    /**
     * 封装阶段列表数据
     * @param paasStageEntityList
     * @param stageWorkMap
     * @param stageHandle
     * @param stageSettingShow com.xbongbong.paas.enums.StageSettingShowEnum
     * @return
     */
    public List<StageListPojo> getStageListPojo(List<PaasStageEntity> paasStageEntityList, Map<Long, List<StageWorkEntity>> stageWorkMap, StageHandle stageHandle, Integer stageSettingShow) {
        if (CollectionsUtil.isEmpty(paasStageEntityList)) {
            return new ArrayList<>();
        }
        List<StageListPojo> stageListPojoList = new ArrayList<>(paasStageEntityList.size());
        for (PaasStageEntity paasStageEntity : paasStageEntityList) {
            StageListPojo stageListPojo = new StageListPojo();
            stageListPojo.setId(paasStageEntity.getId());
            stageListPojo.setName(paasStageEntity.getName());
            stageListPojo.setType(paasStageEntity.getType());
            stageListPojo.setEnable(paasStageEntity.getEnable());
            stageListPojo.setSort(paasStageEntity.getSort());
            stageListPojo.setCode(paasStageEntity.getCode());
            stageListPojo.setIntoProportion(paasStageEntity.getIntoProportion());
            stageListPojo.setOutProportion(paasStageEntity.getOutProportion());
            stageListPojo.setStayLimit(paasStageEntity.getStayLimit());
            stageListPojo.setStayLimitTime(paasStageEntity.getStayLimitTime());
            stageListPojo.setStayLimitTimeUnit(paasStageEntity.getStayLimitTimeUnit());
            stageListPojo.setEnableStageWarningColor(paasStageEntity.getEnableStageWarningColor());
            stageListPojo.setStageWarningColor(paasStageEntity.getStageWarningColor());
            JSONArray executor = Objects.isNull(paasStageEntity.getExecutor()) ? new JSONArray() : paasStageEntity.getExecutor();
            stageListPojo.setExecutor(executor.toJavaList(OptionalRangeEntity.class));
            JSONArray preConditions = Objects.isNull(paasStageEntity.getPreConditions()) ? new JSONArray() : JSONArray.parseArray(paasStageEntity.getPreConditions());
            stageListPojo.setPreConditions(preConditions.toJavaList(StageConditionPojo.class));
            stageListPojo.setAllowSkipStage(paasStageEntity.getAllowSkipStage());
            stageListPojo.setOpenStatus(paasStageEntity.getOpenStatus());
            stageListPojo.setBusinessRelatedStatus(paasStageEntity.getBusinessRelatedStatus());
            stageListPojo.setExtraSetting(paasStageEntity.getExtraSetting());
            stageListPojo.setAllowReactive(paasStageEntity.getAllowReactive());
            JSONArray allowReactiveStage = Objects.isNull(paasStageEntity.getAllowReactiveStage()) ? new JSONArray() : paasStageEntity.getAllowReactiveStage();
            stageListPojo.setAllowReactiveStage(allowReactiveStage.toJavaList(Long.class));
            stageListPojo.setEnableAutoJump(paasStageEntity.getEnableAutoJump());
            stageListPojo.setEnableJumpEnd(paasStageEntity.getEnableJumpEnd());
            stageListPojo.setIsDefault(paasStageEntity.getIsDefault());
            stageListPojo.setLinkOption(paasStageEntity.getLinkOption());

            if (Objects.nonNull(stageWorkMap)) {
                List<StageWorkEntity> stageWorkEntityList = stageWorkMap.get(paasStageEntity.getId());
                stageListPojo.setStageWorkListPojos(getStageWorkListPojo(stageWorkEntityList));
            }

            if (Objects.nonNull(stageHandle)) {
                stageHandle.stageGetSettingAdvance(paasStageEntity, stageListPojo, StageSettingEnum.getByCode(stageSettingShow).getCode());
            }

            stageListPojoList.add(stageListPojo);
        }
        return stageListPojoList;
    }

    /**
     * 封装阶段列表数据
     * @param paasStageEntityList
     * @param stageWorkMap
     * @return
     */
    public List<StageListPojo> getStageListPojo(List<PaasStageEntity> paasStageEntityList, Map<Long, List<StageWorkEntity>> stageWorkMap) {
        return getStageListPojo(paasStageEntityList, stageWorkMap, null, null);
    }

    /**
     * 封装任务列表
     * @param stageWorkEntityList
     * @return
     */
    public List<StageWorkListPojo> getStageWorkListPojo(List<StageWorkEntity> stageWorkEntityList) {
        if (CollectionsUtil.isEmpty(stageWorkEntityList)) {
            return new ArrayList<>();
        }
        List<StageWorkListPojo> stageWorkListPojos = new ArrayList<>(stageWorkEntityList.size());
        for (StageWorkEntity stageWorkEntity : stageWorkEntityList) {
            StageWorkListPojo stageWorkListPojo = new StageWorkListPojo();
            stageWorkListPojo.setId(stageWorkEntity.getId());
            stageWorkListPojo.setName(stageWorkEntity.getName());
            stageWorkListPojo.setDescription(stageWorkEntity.getDescription());
            stageWorkListPojo.setProportion(stageWorkEntity.getProportion());
            stageWorkListPojo.setRequired(stageWorkEntity.getRequired());

            stageWorkListPojos.add(stageWorkListPojo);
        }
        return stageWorkListPojos;
    }

    /**
     * 获取当前流程下的所有已启用阶段
     * @param corpid
     * @param saasMark
     * @param businessType
     * @param formId
     * @param stageProcessId
     * @return
     */
    public List<PaasStageEntity> getStageEnableEntitys(String corpid, Integer saasMark, Integer businessType, Long formId, Long stageProcessId) {
        if (Objects.isNull(corpid) || Objects.isNull(saasMark) || Objects.isNull(formId) || Objects.isNull(stageProcessId)) {
            return new ArrayList<>();
        }
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        params.put(StringConstant.CORPID, corpid);
        params.put(StringConstant.FORM_ID, formId);
        params.put(ParameterConstant.STAGE_PROCESS_ID, stageProcessId);
        params.put(ParameterConstant.ENABLE, EnableEnum.OPEN.getCode());
        params.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        params.put(ParameterConstant.ORDER_BY_STR, " sort " + SortOrder.DESC);

        StageHandle stageHandle = stageHandleFactory.getStageHandle(saasMark, businessType);
        return stageHandle.findEntitys(params);
    }

    /**
     * 获取当前流程版本的所有阶段任务
     * @param corpid
     * @param formId
     * @param stageProcessId
     * @return
     */
    public List<StageWorkEntity> getStageWorkEntityByProcess(String corpid, Long formId, Long stageProcessId) {
        if (Objects.isNull(corpid) || Objects.isNull(formId) || Objects.isNull(stageProcessId)) {
            return new ArrayList<>();
        }
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        params.put(StringConstant.CORPID, corpid);
        params.put(StringConstant.FORM_ID, formId);
        params.put(ParameterConstant.STAGE_PROCESS_ID, stageProcessId);
        params.put(ParameterConstant.ORDER_BY_STR, " sort " + SortOrder.DESC);
        params.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        return stageWorkModel.findEntitys(params);
    }

    /**
     * 获取客户阶段、机会阶段、线索阶段copid=0的默认阶段
     *
     * @param businessType 业务类型
     * @return List<PaasStageEntity>
     */
    public List<PaasStageEntity> getDefaultStage(Integer businessType) {
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        params.put(StringConstant.CORPID, BasicConstant.ZERO_STRING);
        params.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        StageHandle stageHandle = stageHandleFactory.getStageHandle(SaasMarkEnum.SAAS.getCode(), businessType);
        return stageHandle.findEntitys(params);
    }

    /**
     * 获取客户阶段、机会阶段、线索阶段copid=0的默认阶段工作
     *
     * @param stageBusinessType 阶段业务类型【客户阶段：108、机会阶段：304、线索阶段：8005】
     * @return List<StageWorkEntity>
     */
    public List<StageWorkEntity> getDefaultStageWork(Integer stageBusinessType) {
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        params.put(StringConstant.CORPID, BasicConstant.ZERO_STRING);
        params.put(StringConstant.BUSINESS_TYPE, stageBusinessType);
        params.put(StringConstant.SAAS_MARK, SaasMarkEnum.SAAS.getCode());
        params.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        return stageWorkModel.findEntitys(params);
    }

    /**
     * 批量插入阶段数据
     *
     * @param saasMark Saas或Paas标识
     * @param businessType 业务类型
     * @param paasStageList 插入的数据
     */
    public void saveStageList(Integer saasMark, Integer businessType, List<PaasStageEntity> paasStageList, boolean script) {
        StageHandle stageHandle = stageHandleFactory.getStageHandle(saasMark, businessType);
        if (script) {
            stageHandle.insertBatch4Script(paasStageList);
        } else {
            stageHandle.insertBatch(paasStageList);
        }
    }

    /**
     * 更新单条阶段数据
     * @param saasMark Saas或Paas标识
     * @param businessType 业务类型
     * @param paasStageEntity 更新的数据
     * @return 是否成功
     * @throws XbbException
     */
    public void updateStageEntity(Integer saasMark, Integer businessType, PaasStageEntity paasStageEntity) {
        try {
            StageHandle stageHandle = stageHandleFactory.getStageHandle(saasMark, businessType);
            stageHandle.update(paasStageEntity);
        } catch (XbbException e) {
            LOG.error(e.getMsg());
        }
    }

    /**
     * 批量更新阶段数据，不指定corpid，仅初始化脚本使用
     *
     * @param saasMark Saas或Paas标识
     * @param businessType 业务类型
     * @param paasStageList 更新的数据
     */
    public void updateStageBatch4Script(Integer saasMark, Integer businessType, List<PaasStageEntity> paasStageList) {
        StageHandle stageHandle = stageHandleFactory.getStageHandle(saasMark, businessType);
        stageHandle.updateBatch4Script(paasStageList);
    }

    /**
     * 获取当前表单的所有阶段流程
     * @param corpid
     * @param formId
     * @return
     */
    public List<StageProcessEntity> getStageProcessList(String corpid, Long formId) {
        if (Objects.isNull(corpid) || Objects.isNull(formId)) {
            return null;
        }
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        params.put(ParameterConstant.ORDER_BY_STR, " version_id DESC ");
        params.put(StringConstant.CORPID, corpid);
        params.put(StringConstant.FORM_ID, formId);
        params.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
        return stageProcessModel.findEntitys(params);
    }

    public Integer getStageProcessCount(String corpid, Long formId) {
        if (Objects.isNull(corpid) || Objects.isNull(formId)) {
            return null;
        }
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        params.put(ParameterConstant.ORDER_BY_STR, " version_id DESC ");
        params.put(StringConstant.CORPID, corpid);
        params.put(StringConstant.FORM_ID, formId);
        params.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
        return stageProcessModel.getEntitysCount(params);
    }

    /**
     * 获取当前阶段下的所有阶段工作
     * @param corpid
     * @param formId
     * @param stageId
     * @return
     */
    public List<StageWorkEntity> getStageWorkEntityByStage(String corpid, Long formId, Long stageId) {
        if (Objects.isNull(corpid) || Objects.isNull(formId) || Objects.isNull(stageId)) {
            return new ArrayList<>();
        }
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        params.put(StringConstant.CORPID, corpid);
        params.put(StringConstant.FORM_ID, formId);
        params.put(ParameterConstant.STAGE_ID, stageId);
        params.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        return stageWorkModel.findEntitys(params);
    }

    /**
     * 获取表单名-记录日志用
     * @param corpid
     * @param id
     * @return
     * @throws XbbException
     */
    public PaasFormEntityExt getPaasFormEntity(String corpid, Long id) throws XbbException {
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        params.put(StringConstant.CORPID, corpid);
        params.put(ParameterConstant.ID, id);
        params.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        params.put(ParameterConstant.COLUMNS, "id, corpid, name");
        List<PaasFormEntityExt> paasFormEntityExtList = paasFormModel.findEntitys(params);
        if (CollectionsUtil.isEmpty(paasFormEntityExtList)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100028);
        }
        return paasFormEntityExtList.get(0);
    }

    /**
     * 获取当前流程的第一个阶段
     * @param corpid
     * @param saasMark
     * @param businessType
     * @param formId
     * @param stageProcessId
     * @return
     * @throws XbbException
     */
    public PaasStageEntity getFirstStageEntity(String corpid, Integer saasMark, Integer businessType, Long formId, Long stageProcessId) throws XbbException {
        Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        params.put(StringConstant.CORPID, corpid);
        params.put(StringConstant.FORM_ID, formId);
        params.put(ParameterConstant.STAGE_PROCESS_ID, stageProcessId);
        params.put(ParameterConstant.ENABLE, EnableEnum.OPEN.getCode());
        params.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        params.put(ParameterConstant.START, BasicConstant.ZERO);
        params.put(ParameterConstant.PAGE_NUM, BasicConstant.ONE);
        params.put(ParameterConstant.ORDER_BY_STR, " sort DESC ");

        StageHandle stageHandle = stageHandleFactory.getStageHandle(saasMark, businessType);
        List<PaasStageEntity> entitys = stageHandle.findEntitys(params);
        if (CollectionsUtil.isEmpty(entitys)) {
            throw new XbbException(CustomerStageErrorCodeEnum.API_ERROR_238019);
        }
        return entitys.get(0);
    }

    /**
     * 获取当前阶段流程下的所有自定义工作流
     * @param corpid 公司id
     * @param formId 表单id
     * @param stageProcessId 阶段流程id
     * @return 阶段工作流实体
     * @throws XbbException exception
     */
    public List<StageWorkflowEntity> getStageWorkflowEntity(String corpid, Long formId, Long stageProcessId) throws XbbException {
        Map<String, Object> params = new HashMap<>(2 << 2);
        params.put(StringConstant.CORPID, corpid);
        params.put(StringConstant.FORM_ID, formId);
        params.put(ParameterConstant.STAGE_PROCESS_ID, stageProcessId);
        params.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        return stageWorkflowModel.findEntitys(params);
    }

    /**
     * 校验是否是paas表单并且不是旗舰版
     * @param corpid
     * @param saasMark
     * @return
     * @throws XbbException
     */
    public void checkPaasAndNoUltimate(String corpid, Integer saasMark) throws XbbException {
        Integer feeType = packageHelp.getFeeType(corpid);
        if (!Objects.equals(PackageTypeEnum.ULTIMATE.getType(), feeType) && Objects.equals(SaasMarkEnum.PAAS.getCode(), saasMark)) {
            throw new XbbException(OutLinkErrorCodeEnum.API_ERROR_405014);
        }
    }

    /**
     * 封装阶段实体
     * @param paasStageEntity 阶段实体
     * @param stageSavePojo 阶段保存pojo
     * @return PaasStageEntity
     */
    public PaasStageEntity wrapStageEntity(PaasStageEntity paasStageEntity, StageSavePojo stageSavePojo) {
        paasStageEntity.setName(stageSavePojo.getName());
        paasStageEntity.setIntoProportion(stageSavePojo.getIntoProportion());
        paasStageEntity.setOutProportion(stageSavePojo.getOutProportion());
        paasStageEntity.setStayLimit(stageSavePojo.getStayLimit());
        if (Objects.equals(stageSavePojo.getStayLimit(), 1)) {
            paasStageEntity.setStayLimitTime(stageSavePojo.getStayLimitTime());
            paasStageEntity.setStayLimitTimeUnit(stageSavePojo.getStayLimitTimeUnit());
        }
        paasStageEntity.setEnableStageWarningColor(Objects.isNull(stageSavePojo.getEnableStageWarningColor()) ? 0 : stageSavePojo.getEnableStageWarningColor());
        if (Objects.equals(paasStageEntity.getEnableStageWarningColor(), 1)) {
            paasStageEntity.setStageWarningColor(stageSavePojo.getStageWarningColor());
        }
        JSONArray executor = Objects.isNull(stageSavePojo.getExecutor()) ? new JSONArray() : JSONArray.parseArray(JSON.toJSONString(stageSavePojo.getExecutor()));
        paasStageEntity.setExecutor(executor);
        String preConditions = Objects.isNull(stageSavePojo.getPreConditions()) ? new JSONArray().toJSONString() : JSONArray.toJSONString(stageSavePojo.getPreConditions());
        paasStageEntity.setPreConditions(preConditions);
        paasStageEntity.setAllowSkipStage(stageSavePojo.getAllowSkipStage());
        paasStageEntity.setAllowReactive(stageSavePojo.getAllowReactive());
        JSONArray allowReactiveStage = Objects.isNull(stageSavePojo.getAllowReactiveStage()) ? new JSONArray() : JSONArray.parseArray(JSON.toJSONString(stageSavePojo.getAllowReactiveStage()));
        paasStageEntity.setAllowReactiveStage(allowReactiveStage);
        paasStageEntity.setEnableAutoJump(Objects.isNull(stageSavePojo.getEnableAutoJump()) ? 0 : stageSavePojo.getEnableAutoJump());
        paasStageEntity.setEnableJumpEnd(Objects.isNull(stageSavePojo.getEnableJumpEnd()) ? 1 : stageSavePojo.getEnableJumpEnd());
        paasStageEntity.setIsDefault(stageSavePojo.getIsDefault());
        paasStageEntity.setLinkOption(stageSavePojo.getLinkOption());
        JSONObject extraSetting = Objects.isNull(stageSavePojo.getStageExtraSettingPojo()) ? new JSONObject() : JSONObject.parseObject(JSON.toJSONString(stageSavePojo.getStageExtraSettingPojo()));
        paasStageEntity.setExtraSetting(extraSetting);
        paasStageEntity.setOpenStatus(stageSavePojo.getOpenStatus());
        paasStageEntity.setBusinessRelatedStatus(stageSavePojo.getBusinessRelatedStatus());
        return paasStageEntity;
    }

    /**
     * 封装阶段任务实体数据
     * @param stageWorkEntity 阶段实体
     * @param stageWorkPojo 阶段工作pojo
     * @return StageWorkEntity 阶段实体
     */
    public StageWorkEntity wrapStageWorkEntity(StageWorkEntity stageWorkEntity, StageWorkPojo stageWorkPojo) {
        stageWorkEntity.setId(stageWorkPojo.getId());
        stageWorkEntity.setName(stageWorkPojo.getName());
        stageWorkEntity.setDescription(stageWorkPojo.getDescription());
        stageWorkEntity.setProportion(stageWorkPojo.getProportion());
        stageWorkEntity.setSort(stageWorkPojo.getSort());
        stageWorkEntity.setRequired(stageWorkPojo.getRequired());
        JSONArray executor = Objects.isNull(stageWorkPojo.getExecutor()) ? new JSONArray() : JSONArray.parseArray(JSON.toJSONString(stageWorkPojo.getExecutor()));
        stageWorkEntity.setExecutor(executor);
        JSONObject executionEvent = Objects.isNull(stageWorkPojo.getExecutionEvent()) ? new JSONObject() : JSONObject.parseObject(JSON.toJSONString(stageWorkPojo.getExecutionEvent()));
        stageWorkEntity.setExecutionEvent(executionEvent);
        JSONArray completionCondition = Objects.isNull(stageWorkPojo.getCompletionCondition()) ? new JSONArray() : JSONArray.parseArray(JSON.toJSONString(stageWorkPojo.getCompletionCondition()));
        stageWorkEntity.setCompletionCondition(completionCondition);
        stageWorkEntity.setUpdateTime(DateTimeUtil.getInt());

        return stageWorkEntity;
    }

    /**
     * 根据主业务 获取阶段业务类型
     * @param businessType
     * @return
     */
    public Integer getStageBusinessType(Integer businessType) {
        XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(businessType);
        switch (xbbRefTypeEnum) {
            case CUSTOMER_MANAGEMENT:
            case CUSTOMER:
            case CUSTOMER_STAGE:
                return XbbRefTypeEnum.CUSTOMER_STAGE.getCode();
            case SALES_OPPORTUNITY:
            case ALL_OPPORTUNITY:
            case SALE_STAGE:
                return XbbRefTypeEnum.SALE_STAGE.getCode();
            case CLUE:
            case ALL_CLUE:
            case CLUE_STAGE:
                return XbbRefTypeEnum.CLUE_STAGE.getCode();
            case CONTRACT:
                return XbbRefTypeEnum.CONTRACT_STAGE.getCode();
            case PAAS:
            case SYSTEM:
                return XbbRefTypeEnum.PAAS.getCode();
            default:
                return null;
        }
    }

    /**
     * 当前公司是否支持列表页显示阶段停留时长的功能
     * @param corpid
     * @return
     */
    public boolean isSupportStageStayTime(String corpid) {
        boolean supportStageStayTime = false;
        //redis 缓存白名单
        String configValue = paasRedisHelper.getValue(CompanyConfigEnum.STAGE_STAY_TIME.getAlias(), BasicConstant.ZERO_STRING);
        if (StringUtil.isEmpty(configValue)) {
            CompanyConfigEntity companyConfigEntity = companyConfigModel.getByConfigAlias(CompanyConfigEnum.STAGE_STAY_TIME.getAlias(), BasicConstant.ZERO_STRING);
            if (Objects.nonNull(companyConfigEntity)) {
                configValue = companyConfigEntity.getConfigValue();
                //置入缓存
                paasRedisHelper.setValue(CompanyConfigEnum.STAGE_STAY_TIME.getAlias(), BasicConstant.ZERO_STRING, configValue, RedisTimeConstant.TEN_MINUTES);
            }
        }
        List<String> corpids = JSONArray.parseArray(configValue, String.class);
        if (CollectionsUtil.isNotEmpty(corpids) && corpids.contains(corpid)) {
            supportStageStayTime = true;
        }
        return supportStageStayTime;
    }

    /**
     * 更流停留时长 字段
     * @param corpid
     * @param formId
     * @param businessType
     * @param updateData 需要更新的数据
     * @param intoStageTime
     * @param data 当前主数据
     */
    public void packageStageStayTime(String corpid, Long formId, Integer businessType, JSONObject updateData, long intoStageTime, JSONObject data) {
        try {
            PaasFormExplainEntity explainEntity = proFormHelp.getExplainEntity(corpid, formId, businessType);
            String explains = explainEntity.getExplains();
            String firstIntoStageTimeAttr = "";
            String nowIntoStageTimeAttr = "";
            FieldAttrEntity nowIntoStageTimeEntity = ExplainUtil.getFieldWithFieldType(explains, FieldTypeEnum.NOW_INTO_STAGE_TIME.getType());
            if (Objects.nonNull(nowIntoStageTimeEntity)) {
                nowIntoStageTimeAttr = nowIntoStageTimeEntity.getAttr();
            }

            FieldAttrEntity firstIntoStageTimeEntity = ExplainUtil.getFieldWithFieldType(explains, FieldTypeEnum.FIRST_INTO_STAGE_TIME.getType());
            if (Objects.nonNull(firstIntoStageTimeEntity)) {
                // 只有新建数据 或者从开始阶段跳转的数据的时候才会更新初次阶段进入时间，判断依据是主数据里面没有存，存了之后，不会对该字段的值进行更改
                if (Objects.nonNull(data) && Objects.isNull(data.getLong(firstIntoStageTimeEntity.getAttr()))) {
                    firstIntoStageTimeAttr = firstIntoStageTimeEntity.getAttr();
                }
            }

            if (StringUtil.isNotEmpty(firstIntoStageTimeAttr)) {
                updateData.put(firstIntoStageTimeAttr, intoStageTime);
            }
            if (StringUtil.isNotEmpty(nowIntoStageTimeAttr)) {
                updateData.put(nowIntoStageTimeAttr, intoStageTime);
            }
        } catch (XbbException e) {
            LOG.error("StageHelp.packageStageStayTime 出错：", e);
        }
    }

    /**
     * 根据stageCode 返回 PaasStageEntity 的Map
     * @param corpid
     * @param formId
     * @param businessType
     * @param saasMark
     * @param enable
     * @return
     */
    public Map<String, PaasStageEntity> getStageCode2StageEntityMap(String corpid, Long formId, Integer businessType, Integer saasMark, Integer enable) {
        Map<String, Object> params = new HashMap<>();
        params.put(ParameterConstant.CORPID, corpid);
        params.put(ParameterConstant.FORMID, formId);
        params.put(ParameterConstant.DEL, BasicConstant.ZERO);
        params.put(ParameterConstant.ORDER_BY_STR, BasicConstant.SORT + " " + SortOrder.DESC);
        params.put(ParameterConstant.ENABLE, enable);

        StageHandle stageHandle = stageHandleFactory.getStageHandle(saasMark, businessType);
        List<PaasStageEntity> stageList = stageHandle.findEntitys(params);
        return stageList.stream().collect(Collectors.toMap(PaasStageEntity::getCode, Function.identity(), (v1, v2) -> v2));
    }

    /**
     * 根据【阶段进入时间】及【阶段结束时间】判断是否超时
     * @param stayLimitTime
     * @param stayLimitTimeUnit
     * @param intoTime
     * @param outTime
     * @return
     */
    public boolean isTimeout(Integer stayLimitTime, Integer stayLimitTimeUnit, Long intoTime, Long outTime) {
        if (Objects.isNull(intoTime) || Objects.isNull(outTime) || Objects.isNull(stayLimitTime) || Objects.isNull(stayLimitTimeUnit)) {
            return false;
        }
        Map<Integer, Integer> timeOutSetMap = new HashMap<>();
        timeOutSetMap.put(1, TimeConstant.SECONDS_PER_HOUR);
        timeOutSetMap.put(2, TimeConstant.SECONDS_PER_DAY);
        timeOutSetMap.put(3, TimeConstant.SECONDS_PER_WEEK);
        timeOutSetMap.put(4, TimeConstant.SECONDS_PER_MONTH);
        //阶段停留时长
        long requiredStageStayTime = (long) stayLimitTime * timeOutSetMap.get(stayLimitTimeUnit);
        long realityStageStayTime = outTime - intoTime;
        //若超时（实际停留 >= 设置停留）返回true
        return requiredStageStayTime <= realityStageStayTime;
    }

    /**
     * 为阶段停留超时的数据设置超时颜色预警
     *
     * @param formDataListDTO   列表页入参
     * @param dataList    数据列表
     * @param headList 字段
     */
    public void setWarningColorData(FormDataListDTO formDataListDTO, List<PaasFormDataEntityExt>  dataList, List<FieldAttrEntity> headList){
        // 判断是否阶段推进器相关业务
        if (!XbbRefTypeEnum.isSupportStageProcess(formDataListDTO.getSaasMark(), formDataListDTO.getBusinessType())) {
            return;
        }
        // 获取阶段推进器字段
        FieldAttrEntity stageFieldAttr = ExplainUtil.getFieldWithFieldType(headList, FieldTypeEnum.STAGE_THRUSTER.getType());
        if (Objects.isNull(stageFieldAttr) || Objects.equals(stageFieldAttr.getIsOpen(), 0)) {
            return;
        }
        // 获取当前阶段进入时间字段
        FieldAttrEntity nowIntoStageTimeFieldAttr = ExplainUtil.getFieldWithFieldType(headList, FieldTypeEnum.NOW_INTO_STAGE_TIME.getType());
        if (Objects.isNull(nowIntoStageTimeFieldAttr) || Objects.equals(nowIntoStageTimeFieldAttr.getIsOpen(), 0)) {
            return;
        }
        // 判断客户白名单
        if(!isSupportStageStayTime(formDataListDTO.getCorpid())) {
            return;
        }
        // 获取阶段code和阶段实体的对应关系
        Map<String, PaasStageEntity> stageCode2StageEntityMap = getStageCode2StageEntityMap(formDataListDTO.getCorpid(), formDataListDTO.getFormId(), formDataListDTO.getBusinessType(), formDataListDTO.getSaasMark(), 1);

        for (PaasFormDataEntityExt paasFormDataEsEntity : dataList) {
            JSONObject dataJsonObject = paasFormDataEsEntity.getData();

            String stageCode = dataJsonObject.getString(stageFieldAttr.getAttr());
            if (StringUtil.isEmpty(stageCode)) {
                continue;
            }
            PaasStageEntity stageEntity = stageCode2StageEntityMap.get(stageCode);
            // 判断是否开启颜色预警
            if (Objects.isNull(stageEntity) || !Objects.equals(stageEntity.getEnableStageWarningColor(), BasicConstant.ONE)) {
                continue;
            }

            // 判断是否超时
            Long intoTime = dataJsonObject.getLong(nowIntoStageTimeFieldAttr.getAttr());
            if (isTimeout(stageEntity.getStayLimitTime(), stageEntity.getStayLimitTimeUnit(), intoTime, DateTimeUtil.getInt())) {
                Map<String, Map<String, String>> cellStyle = new HashMap<>();
                Map<String, String> backgroundColor = new HashMap<>();
                backgroundColor.put("backgroundColor", stageEntity.getStageWarningColor());
                cellStyle.put(stageFieldAttr.getAttr(), backgroundColor);
                paasFormDataEsEntity.setCellStyle(cellStyle);
            }
        }
    }

    /**
     * 从阶段推进器的字段解释中获取多版本启用时设置的默认版本
     *
     * @param corpid
     * @param formId
     * @return
     */
    public Long getMultiVersionDefaultStageProcess(String corpid, Long formId) {
        try {
            PaasFormExplainEntity paasFormExplain = paasFormExplainModel.getByFormId(formId, corpid);
            List<FieldAttrEntity> explainList = JSON.parseArray(paasFormExplain.getExplains(), FieldAttrEntity.class);
            FieldAttrEntity stageField = explainList.stream().filter(field -> Objects.equals(field.getFieldType(), FieldTypeEnum.STAGE_THRUSTER.getType())).findFirst().orElse(null);
            if (Objects.nonNull(stageField)) {
                return stageField.getDefaultStageProcessId();
            }
        } catch (XbbException e) {
            LOG.error("StageHelp.getMultiVersionDefaultStageProcess error", e);
        }
        return null;
    }
}
